﻿// ------------------------------------------------------------------------------
// <copyright file="MenuItem.cs" company="skumaronline.com">
//    Copyright (C) 2012 Suresh Kumar T.
//
//    This program is free software; you can redistribute it and/or
//    modify it under the terms of the GNU General Public License
//    as published by the Free Software Foundation version 2
//    of the License.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    http://www.gnu.org/licenses/gpl-2.0.html
//
// </copyright>
// ------------------------------------------------------------------------------

namespace StoreAppLib.Controls
{
    using StoreAppLib.Animations;
    using Windows.UI;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Media;

    /// <summary>
    /// Menu Item
    /// </summary>
    [TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
    [TemplateVisualState(Name = "PointerOver", GroupName = "CommonStates")]
    [TemplateVisualState(Name = "Pressed", GroupName = "CommonStates")]
    [TemplatePartAttribute(Name = "ItemBackground", Type = typeof(Border))]
    public class MenuItem : ContentControl, IMenuItem
    {
        /// <summary>
        /// Id dependency property
        /// </summary>
        public static readonly DependencyProperty IdProperty =
            DependencyProperty.Register("Id", typeof(object), typeof(MenuItem), new PropertyMetadata(null));

        /// <summary>
        /// Label dependency property
        /// </summary>
        public static readonly DependencyProperty LabelProperty =
            DependencyProperty.Register("Label", typeof(string), typeof(MenuItem), new PropertyMetadata(null));

        /// <summary>
        /// Pointer Over Background value dependency property
        /// </summary>
        public static readonly DependencyProperty PointerOverBackgroundProperty =
            DependencyProperty.Register("PointerOverBackground", typeof(SolidColorBrush), typeof(MenuItem), new PropertyMetadata(new SolidColorBrush(Colors.Transparent)));

        /// <summary>
        /// Pressed Background value dependency property
        /// </summary>
        public static readonly DependencyProperty PressedBackgroundProperty =
            DependencyProperty.Register("PressedBackground", typeof(SolidColorBrush), typeof(MenuItem), new PropertyMetadata(new SolidColorBrush(Colors.Transparent)));

        /// <summary>
        /// Separator color dependency property
        /// </summary>
        public static readonly DependencyProperty SeparatorColorProperty =
            DependencyProperty.Register("SeparatorColor", typeof(SolidColorBrush), typeof(MenuItem), new PropertyMetadata(Menu.MenuSeparatorColor));

        /// <summary>
        /// Separator thickness dependency property
        /// </summary>
        public static readonly DependencyProperty SeparatorThicknessProperty =
            DependencyProperty.Register("SeparatorThickness", typeof(double), typeof(MenuItem), new PropertyMetadata(Menu.MenuSeparatorThickness));

        /// <summary>
        /// Indicating whether mouse is down
        /// </summary>
        private static bool isMouseDown;

        /// <summary>
        /// Border that represent the background
        /// </summary>
        private Border itemBackground;

        /// <summary>
        /// Initializes a new instance of the <see cref="MenuItem" /> class.
        /// </summary>
        public MenuItem()
        {
            this.DefaultStyleKey = typeof(MenuItem);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="MenuItem" /> class.
        /// </summary>
        /// <param name="menuItem">The menu item defined in the container page</param>
        internal MenuItem(IMenuItem menuItem)
        {
            this.XMALMenuItem = menuItem;

            this.MinHeight = 40;

            this.DefaultStyleKey = typeof(MenuItem);

            isMouseDown = false;
        }

        /// <summary>
        /// Gets or sets menu item defined in the container page.
        /// </summary>
        public IMenuItem XMALMenuItem { get; set; }

        /// <summary>
        /// Gets or sets the label
        /// </summary>
        public string Label
        {
            get
            {
                return (string)this.GetValue(LabelProperty);
            }

            set
            {
                this.SetValue(LabelProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets the Id
        /// </summary>
        public object Id
        {
            get
            {
                return this.GetValue(IdProperty);
            }

            set
            {
                this.SetValue(IdProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets Separator thickness property.
        /// </summary>
        /// <value>
        /// The Separator thickness.
        /// </value>
        public double SeparatorThickness
        {
            get
            {
                return (double)this.GetValue(SeparatorThicknessProperty);
            }

            set
            {
                this.SetValue(SeparatorThicknessProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets Separator color property.
        /// </summary>
        /// <value>
        /// The Separator color.
        /// </value>
        public SolidColorBrush SeparatorColor
        {
            get
            {
                return (SolidColorBrush)this.GetValue(SeparatorColorProperty);
            }

            set
            {
                this.SetValue(SeparatorColorProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets Pointer Over Background property.
        /// </summary>
        /// <value>
        /// The Pointer Over Background.
        /// </value>
        public SolidColorBrush PointerOverBackground
        {
            get
            {
                return (SolidColorBrush)this.GetValue(PointerOverBackgroundProperty);
            }

            set
            {
                this.SetValue(PointerOverBackgroundProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets Pressed Background property.
        /// </summary>
        /// <value>
        /// The Pressed Background.
        /// </value>
        public SolidColorBrush PressedBackground
        {
            get
            {
                return (SolidColorBrush)this.GetValue(PressedBackgroundProperty);
            }

            set
            {
                this.SetValue(PressedBackgroundProperty, value);
            }
        }

        /// <summary>
        /// Invoked whenever application code or internal processes (such as a rebuilding
        /// layout pass) call ApplyTemplate. In simplest terms, this means the method
        /// is called just before a UI element displays in your app. Override this method
        /// to influence the default post-template logic of a class.
        /// </summary>
        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.itemBackground = this.GetTemplateChild("ItemBackground") as Border;

            if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
            {
                return;
            }

            if (this.XMALMenuItem is MenuItem)
            {
                MenuItem item = this.XMALMenuItem as MenuItem;
                TextBlock textBlock = new TextBlock() { Text = item.Label };
                textBlock.HorizontalAlignment = this.HorizontalContentAlignment;
                textBlock.VerticalAlignment = VerticalAlignment.Center;
                this.Content = textBlock;
            }
            else if (this.XMALMenuItem is MenuSeparator)
            {
                Border line = new Border();
                line.Height = this.SeparatorThickness;
                line.BorderThickness = new Thickness(this.SeparatorThickness / 2);
                line.BorderBrush = this.SeparatorColor;
                line.Background = this.Background;
                line.HorizontalAlignment = HorizontalAlignment.Stretch;
                line.VerticalAlignment = VerticalAlignment.Center;
                this.Content = line;
            }
        }

        /// <summary>
        /// Called before the PointerEntered event occurs
        /// </summary>
        /// <param name="e">Event data for the event</param>
        protected override void OnPointerEntered(Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
        {
            base.OnPointerEntered(e);

            if (this.XMALMenuItem is MenuSeparator)
            {
                return;
            }

            if (isMouseDown)
            {
                AnimationHelper.ObjectAnimationUsingKeyFrames(this.itemBackground, "(Border.Background).(SolidColorBrush.Color)", this.PressedBackground.Color, 0);
            }
            else
            {
                AnimationHelper.ObjectAnimationUsingKeyFrames(this.itemBackground, "(Border.Background).(SolidColorBrush.Color)", this.PointerOverBackground.Color, 0);
            }
        }

        /// <summary>
        /// Called before the PointerExited event occurs
        /// </summary>
        /// <param name="e">Event data for the event</param>
        protected override void OnPointerExited(Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
        {
            base.OnPointerExited(e);

            if (this.XMALMenuItem is MenuSeparator)
            {
                return;
            }

            AnimationHelper.ObjectAnimationUsingKeyFrames(this.itemBackground, "(Border.Background).(SolidColorBrush.Color)", Colors.Transparent, 0);
        }

        /// <summary>
        /// Called before the GotFocus event occurs
        /// </summary>
        /// <param name="e">The data for the event</param>
        protected override void OnGotFocus(RoutedEventArgs e)
        {
            base.OnGotFocus(e);

            if (this.XMALMenuItem is MenuSeparator)
            {
                return;
            }

            AnimationHelper.ObjectAnimationUsingKeyFrames(this.itemBackground, "(Border.Background).(SolidColorBrush.Color)", this.PointerOverBackground.Color, 0);
        }

        /// <summary>
        /// Called before the LostFocus event occurs
        /// </summary>
        /// <param name="e">The data for the event</param>
        protected override void OnLostFocus(RoutedEventArgs e)
        {
            base.OnLostFocus(e);

            if (this.XMALMenuItem is MenuSeparator)
            {
                return;
            }

            AnimationHelper.ObjectAnimationUsingKeyFrames(this.itemBackground, "(Border.Background).(SolidColorBrush.Color)", Colors.Transparent, 0);
        }

        /// <summary>
        /// Called before the PointerPressed event occurs
        /// </summary>
        /// <param name="e">Event data for the event</param>
        protected override void OnPointerPressed(Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
        {
            isMouseDown = true;

            this.CapturePointer(e.Pointer);

            if (this.XMALMenuItem is MenuSeparator)
            {
                return;
            }

            AnimationHelper.ObjectAnimationUsingKeyFrames(this.itemBackground, "(Border.Background).(SolidColorBrush.Color)", this.PressedBackground.Color, 0);
        }

        /// <summary>
        /// Called before the PointerReleased event occurs
        /// </summary>
        /// <param name="e">Event data for the event</param>
        protected override void OnPointerReleased(Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
        {
            isMouseDown = false;

            if (this.XMALMenuItem is MenuSeparator)
            {
                return;
            }

            AnimationHelper.ObjectAnimationUsingKeyFrames(this.itemBackground, "(Border.Background).(SolidColorBrush.Color)", Colors.Transparent, 0);

            this.ReleasePointerCapture(e.Pointer);
        }
    }
}
